package chat.client;

import java.io.IOException;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.channels.SocketChannel;

import chat.Message;
import chat.ReadMessageStatus;
import chat.client.statemachine.ListOfAlgorithms;
import chat.statemachine.AlgorithmActionInvocationException;

/**
 * This class contains the chat client's thread waiting for keyboard inputs.
 * 
 * @author chris
 * @author Denis Conan
 * 
 */
public class ChatClient implements Runnable {

	private Socket rwCon;
	private Message inMessage, outMessage;
	private InetSocketAddress rcvAddress;
	private ChatClientState cstate;

	public ChatClient(final String destHost, final int port,
			final ChatClientState state) throws SocketException,
			UnknownHostException, IOException {
		cstate = state;
		SocketChannel rwChan;
		try {
			InetAddress destAddr = InetAddress.getByName(destHost);
			rwChan = SocketChannel.open();
			rwCon = rwChan.socket();
			// on recupere l'adresse IP de la machine cible
			rcvAddress = new InetSocketAddress(destAddr, port);
			// on connecte le socket d'emission au port distant
			rwCon.connect(rcvAddress);
			inMessage = new Message(rwChan);
			outMessage = new Message(rwChan);


		} catch (SocketException se) {
			se.printStackTrace();
		} catch (UnknownHostException ue) {
			ue.printStackTrace();

		}
	}

	public long sendMsg(final int type, final int identity, final Serializable s)
	throws IOException {
		long res = -1L;
		outMessage.setMessage(type, identity, 0, s);
		res = outMessage.write();
		return res;
	}

	public void close() throws IOException {
		inMessage.close();
		outMessage.close();
		rwCon.close();
	}

	public void run() {
		ReadMessageStatus messState;
		while (true) {
			// reception d'un message et affichage
			try {
				messState = inMessage.readMessage();
				if (messState == ReadMessageStatus.ChannelClosed) {
					break;
				} 
				else {
					if (messState == ReadMessageStatus.ReadDataCompleted) {
						ListOfAlgorithms.execute(cstate,
								inMessage.getType(), inMessage.getData());
					}
				}
			} catch (IOException e) {
				System.out.println(e);
				return;
			} catch (AlgorithmActionInvocationException e) {
				System.out.println(e);
			}
			System.out.println("Fin de reception d'un message");
		}
	}
}
